package com.secret.dao.impl;

import com.secret.dao.BaseDao;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;

//@Transactional//事务处理的注解
@Repository
public class BaseDaoImpl<T> implements BaseDao<T> {
	
	@Autowired
	private SessionFactory sessionFactory;
	private static ThreadLocal<Transaction> sThreadLocal = new ThreadLocal<>();

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}
	
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
	private Session getCurrentSession() {
		Session session = sessionFactory.openSession();
		//事务必须是开启的，否则获取不到
		Transaction transaction = sThreadLocal.get();
		if (transaction == null) {
			transaction = session.beginTransaction();
			sThreadLocal.set(transaction);
		}
		return session;
	}

	public void close(){
		Transaction transaction = sThreadLocal.get();
		if (transaction != null) {
			transaction.commit();
			sThreadLocal.remove();
		}
	}

	public Serializable save(T o) {
		Serializable s=this.getCurrentSession().save(o);
		this.getCurrentSession().flush();
		return s;
		
	}

	/**
	 * 批处理，保存List对象，每次保存 500 条刷新
	 * @param list
	 * @return
	 */
	public void saveBatch(List<T> list){
		Session session = this.getCurrentSession();
		if(list!=null){
			for(int i=0;i<list.size();i++ ){
				T o = list.get(i);
				session.save(o);
				if(i%500==0){//以每500个数据作为一个处理单元
					session.flush(); //保持与数据库数据的同步
					session.clear(); //清除内部缓存的全部数据，及时释放出占用的内存
				}
			}
			//最后在释放一次缓存
			session.flush();
			session.clear();
		}
	}



	public void delete(T o) {
		this.getCurrentSession().delete(o);
		this.getCurrentSession().flush();
	}

	public void deleteBatch(List<T> list){
		Session session = this.getCurrentSession();
		if(list!=null){
			for(int i=0;i<list.size();i++ ){
				T o = list.get(i);
				session.delete(o);
				if(i%500==0){//以每500个数据作为一个处理单元
					session.flush(); //保持与数据库数据的同步
					session.clear(); //清除内部缓存的全部数据，及时释放出占用的内存
				}
			}
			//最后在释放一次缓存
			session.flush();
			session.clear();
		}
	}

	public void update(T o) {
		this.getCurrentSession().update(o);
		this.getCurrentSession().flush();
	}

	public void saveOrUpdate(T o) {
		this.getCurrentSession().saveOrUpdate(o);
		this.getCurrentSession().flush();
	}

	public List<T> find(String hql) {
		return this.getCurrentSession().createQuery(hql).list();
	}

	public List<T> find(String hql, Object[] param) {
		Query q = this.getCurrentSession().createQuery(hql);
		if (param != null && param.length > 0) {
			for (int i = 0; i < param.length; i++) {
				q.setParameter(i, param[i]);
			}
		}
		return q.list();
	}

	public List<T> find(String hql, List<Object> param) {
		Query q = this.getCurrentSession().createQuery(hql);
		if (param != null && param.size() > 0) {
			for (int i = 0; i < param.size(); i++) {
				q.setParameter(i, param.get(i));
			}
		}
		return q.list();
	}

	public List<T> find(String hql, Object[] param, Integer page, Integer rows) {
		if (page == null || page < 1) {
			page = 1;
		}
		if (rows == null || rows < 1) {
			rows = 10;
		}
		Query q = this.getCurrentSession().createQuery(hql);
		if (param != null && param.length > 0) {
			for (int i = 0; i < param.length; i++) {
				q.setParameter(i, param[i]);
			}
		}
		return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
	}

	public List<T> find(String hql, List<Object> param, Integer page,
			Integer rows) {
		if (page == null || page < 1) {
			page = 1;
		}
		if (rows == null || rows < 1) {
			rows = 10;
		}
		Query q = this.getCurrentSession().createQuery(hql);
		if (param != null && param.size() > 0) {
			for (int i = 0; i < param.size(); i++) {
				q.setParameter(i, param.get(i));
			}
		}
		return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
	}

	public T get(Class<T> c, Serializable id) {
		return (T) this.getCurrentSession().get(c, id);
	}

	public T get(String hql, Object[] param) {
		List<T> l = this.find(hql, param);
		if (l != null && l.size() > 0) {
			return l.get(0);
		} else {
			return null;
		}
	}

	public T get(String hql, List<Object> param) {
		List<T> l = this.find(hql, param);
		if (l != null && l.size() > 0) {
			return l.get(0);
		} else {
			return null;
		}
	}

	public Long count(String hql) {
		return (Long) this.getCurrentSession().createQuery(hql).uniqueResult();
	}

	public Long count(String hql, Object[] param) {
		Query q = this.getCurrentSession().createQuery(hql);
		if (param != null && param.length > 0) {
			for (int i = 0; i < param.length; i++) {
				q.setParameter(i, param[i]);
			}
		}
		return (Long) q.uniqueResult();
	}

	public Long count(String hql, List<Object> param) {
		Query q = this.getCurrentSession().createQuery(hql);
		if (param != null && param.size() > 0) {
			for (int i = 0; i < param.size(); i++) {
				q.setParameter(i, param.get(i));
			}
		}
		return (Long) q.uniqueResult();
	}

	public Integer executeHql(String hql) {
		return this.getCurrentSession().createQuery(hql).executeUpdate();
	}

	public Integer executeHql(String hql, Object[] param) {
		Query q = this.getCurrentSession().createQuery(hql);
		if (param != null && param.length > 0) {
			for (int i = 0; i < param.length; i++) {
				q.setParameter(i, param[i]);
			}
		}
		return q.executeUpdate();
	}

	public void executeSql(String sql) {
		// 方法过时 换个方法
		// SQLQuery query = this.getCurrentSession().createSQLQuery(sql);
		Query query = this.getCurrentSession().createNativeQuery(sql);
		query.executeUpdate();
	}

	public Integer executeHql(String hql, List<Object> param) {
		Query q = this.getCurrentSession().createQuery(hql);
		if (param != null && param.size() > 0) {
			for (int i = 0; i < param.size(); i++) {
				q.setParameter(i, param.get(i));
			}
		}
		return q.executeUpdate();
	}

	public List<T> find(Criteria cr, Integer page, Integer rows) {
		cr.setFirstResult((page-1)*rows);//开始的行号  
		cr.setMaxResults(rows);//每页多少行
		return cr.list();
	}



	/**
	 * sql查询返回List<Object[]>
	 * 每一个Object[]代表一条数据
	 */
	public List<Object[]> getBySqlObject(String sql){
		Session session = this.getCurrentSession();
		List<Object[]> list = session.createSQLQuery(sql).list();
		return list;
	}

	/**
	 * sql查询返回List<T>
	 * 每一个 T 代表一条数据
	 */
	public List<T> getBySql(String sql,Class<T> c){
		Session session = this.getCurrentSession();
		List<T> list = session.createSQLQuery(sql).addEntity(c).list();
		return list;
	}
	public List<T> getBySql(String sql, Object[] param,Class<T> c) {
		Session session = this.getCurrentSession();
		Query q = session.createSQLQuery(sql).addEntity(c);
		if (param != null && param.length > 0) {
			for (int i = 0; i < param.length; i++) {
				q.setParameter(i, param[i]);
			}
		}
		return q.list();
	}
	public List<T> getBySql(String sql, Object[] param,Integer page, Integer rows,Class<T> c){
		Session session = this.getCurrentSession();
		Query q = session.createSQLQuery(sql).addEntity(c);
		if (page == null || page < 1) {
			page = 1;
		}
		if (rows == null || rows < 1) {
			rows = 10;
		}
		if (param != null && param.length > 0) {
			for (int i = 0; i < param.length; i++) {
				q.setParameter(i, param[i]);
			}
		}
		return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
	}

}
